#ifndef JUEGO_H_
#define JUEGO_H_

#define NO_ESTA_UNIDO -1

#include "Partida.h"
#include "Thread.h"
#include "Usuario.h"
#include "InterfaceDeComunicacion.h"
#include "VistaEscenario.h"
#include "VentanaPrincipal.h"
#include "Socket.h"
#include "ClientSocketReceiver.h"
#include "ReproductorWav.h"

#include <sigc++/sigc++.h>
#include <gtkmm.h>
#include <jsoncpp/json.h>
#include <list>
#include <string>

/* Sonidos disponibles */
enum {SON_CLICK, SON_ERROR, SON_MOVIMIENTO, 
      SON_COMBINACION, SON_GANADOR, SON_INICIO, 
      SON_ABANDONO, SON_SIN_MOVIMIENTOS};

class VistaFichaTablero;

class Juego : public Thread, public sigc::trackable,
    public InterfaceDeComunicacion {
    void *run();

    void finalizarJuego();
    bool estaEjecutando();

    int obtenerIdPartida();

    void mostrarPantallaLogin();
    void lanzarAviso(std::string mensaje_pantalla);
    void mostrarPantallaEleccionPartida(Json::Value niveles);

    void conectarEventos();
    void borrarUsuario(int id, std::string nick);

    void retirarPartida(bool notificarRetiro);
    void volverSalaPartidas();
    void borrarPartida(int idPartido);
    void comenzarPartida();
    void crearPartida();

    void agregarPartida(int idPartido, int jugNec, std::string jugConec,
                        int nivel,
                        BotonPartida *bE, 
                        BotonPartida *bS, 
                        bool meTengoQueUnir);
    void unirmeAPartida(int idPartida);

    void agregarUsuario(int idPartida, std::string nick);

    void notificarFinPartida(Json::Value notificacion);

    void terminarJuego();

    bool conectarAlServidor();
    void solicitarPartidas();
    void solicitarNivel();
    void cargarPartidas(Json::Value jpartidas);
    void loguearUsuario();
    void registrarUsuario();

    void iniciarHilosEnvioRecepcion();

    void notificar(Json::Value mensaje);
    void avisarCambioInterface();

    void cargarAudioPredeterminado(bool completo);

    Partida *partida;
    Glib::Dispatcher avisador;

    Json::Value *jsonCompartido;
    

    Socket clienteEnviar;
    ClientSocketReceiver *clienteRecibir;

    Usuario usuario;
    bool *finalizoTarea;
    VentanaPrincipal *ventanaPrincipal;
    int nivel, idPartidaAsistente;

    // para el hilo que enviar, el que recibe, y para aceptar o rechaz
    // invitaciones
    std::string bufferEnviar, bufferRecibir, estadoCliente;

    VistaEscenario vistaEscenario;

    Mutex *sincronizarTareas;
    int puerto_servidor;
    std::string direccion_servidor;

    void mute();

  public:
    explicit Juego(VentanaPrincipal *ventanaPrincipal);
    virtual ~Juego();

    void seleccionarFicha(VistaFichaTablero *vista);

    bool iniciar();
    void movimientoFicha(int x, int y);
    void unirAPartida(int idPartida);
    void salirPartida(int idPartida);

    void setPuertoServidor(int puerto);
    void setDireccionServidor(std::string direccion);

    static ReproductorWav reproductorWav;
};

#endif
